<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <style>
    div {
      background-color: #666;
      height: 300px;
    }
  </style>
  <body style="height: 2000px;">
    <div></div>
  </body>
  <script>
    let dom = document.getElementsByTagName("div")[0];
    dom.onmousemove = throttle(listenMoveOn, 1000, {leading: true});

    function listenMoveOn(...args) {
      // 监听的回调做一些事情
      console.log("this", this);
      console.log("args", args);
    }

    function throttle(fn, wait, options) {
        let timer, now, context, args;
        old = 0
        if (!options) options = {leading: true, trailing: false}

        const later = () => {
            old = now
            clearTimeout(timer)
            timer = null
            fn.apply(context, args)
        }

        return function () {
            now = +new Date()
            context = this
            args = arguments
            
            if (options.leading && now - old > wait) {
                if (timer) {
                    clearTimeout(timer)
                    timer = null
                }
                old = now
                fn.apply(context, args)
            } 
            if (options.trailing && !timer) {
                timer = setTimeout(later, wait)
            }
        }

    }

    // 会被立即触发，最后一次不会触发
    function throttle1(fn, wait) {
        let timer, old, now, context, args;
        old = +new Date()
        console.log('old', old)

        return function() {
            now = +new Date()
            context = this
            args = arguments
            if (now - old > wait) {
                fn.apply(context, args)
                old = now
            }
        }
    }
    // 不会被立即触发，最后一次会触发
    function throttle2(fn, wait) {
        let timer, context, args;

        return function() {
            context = this
            args = arguments
            if (!timer) {
                timer = setTimeout(() => {
                    timer = null
                    fn.apply(context, args)
                }, wait)
            }
        }
    }
  </script>
</html>
